﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace wsy
{
    /// <summary>
    /// dynamic 反射加载Microsoft.mshtml.dll version7
    /// </summary>
    public partial class ehttp
    {
        static ehttp()
        {
            IHTMLDocument2 = Assembly.Load(Properties.Resources.Microsoft_mshtml).GetType("mshtml.IHTMLDocument2");

        }

        public static Type IHTMLDocument2 { get; set; }
        public static dynamic GetHtmlDoc(IntPtr hwnd)
        {
            try
            {
                RegisterWindowMessage("WM_HTML_GETOBJECT");
                var docobject = new object();
                var tempint = 0;
                var guidIeDocument2 = IHTMLDocument2.GUID;
                var wmHtmlGetobject = RegisterWindowMessage("WM_Html_GETOBJECT");
                var w = SendMessage(hwnd, wmHtmlGetobject, 0, ref tempint);
                ObjectFromLresult(w, ref guidIeDocument2, 0, ref docobject);
                return IHTMLDocument2.IsInstanceOfType(docobject) ? docobject : null;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static IHTMLDocument2Collection GetAllHtmlDoc()
        {
            return GetHtmlDoc(null, IHTMLDocument2Opt.All);
        }

        public static IHTMLDocument2Collection GetHtmlDoc(string url, IHTMLDocument2Opt opt)
        {
            EnumWins.EnumWindows em = new EnumWins.EnumWindows();
            em.GetAllWindows();
            IHTMLDocument2Collection items = new IHTMLDocument2Collection();
            foreach (EnumWins.EnumWindowsItem item in em.Items.Cast<EnumWins.EnumWindowsItem>().Where(s => s.ClassName == "Internet Explorer_Server"))
            {
                switch (opt)
                {
                    case IHTMLDocument2Opt.Equals:
                        if (GetHtmlDoc(item.Handle).url == url) items.Add(item.Handle);
                        break;

                    case IHTMLDocument2Opt.StartWith:
                        if (GetHtmlDoc(item.Handle).url.StartsWith(url)) items.Add(item.Handle);
                        break;

                    case IHTMLDocument2Opt.EndWith:
                        if (GetHtmlDoc(item.Handle).url.EndsWith(url)) items.Add(item.Handle);
                        break;

                    case IHTMLDocument2Opt.All:
                        items.Add(item.Handle);
                        break;
                }
            }
            return items;
        }

        public enum IHTMLDocument2Opt
        {
            Equals,
            StartWith,
            EndWith,
            All
        }

        public class IHTMLDocument2Collection : ReadOnlyCollectionBase
        {
            public dynamic this[int index]
            {
                get { return InnerList[index]; }
            }

            public void Add(IntPtr hWnd)
            {
                dynamic item = GetHtmlDoc(hWnd);
                if (item != null) InnerList.Add(item);
            }
        }

        #region API

        [DllImport("user32.dll", EntryPoint = "RegisterWindowMessage")]
        protected static extern int RegisterWindowMessage(string lpString);

        [DllImport("OLEACC.DLL", EntryPoint = "ObjectFromLresult")]
        protected static extern int ObjectFromLresult(int lResult, ref Guid riid, int wParam,
            [MarshalAs(UnmanagedType.Interface), In, Out] ref object ppvObject);

        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        protected static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, ref int lParam);

        #endregion API
    }
}